package org.smth.search.fetcher.impl;

import com.google.inject.Inject;
import com.google.inject.Injector;

import org.smth.search.fetcher.BoardFetcher;
import org.smth.search.fetcher.FetcherThread;
import org.smth.search.persistence.DataService;
import org.smth.search.types.Post;
import org.smth.search.types.PostItem;

import java.util.AbstractList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Callable;

public class FetcherThreadImpl extends RunnableBase implements FetcherThread, Callable<Object> {

	private Injector injector;

	public void setInjector(Injector injector) {
		this.injector = injector;
	}

	protected Callable<Object> createRunnable() {
		this.fetcher = injector.getInstance(BoardFetcher.class);
		return this;
	}

	protected String board;

	public String getCurrentBoard() {
		return board;
	}

	protected int current;

	public int getCurrentProcessed() {
		return current;
	}

	protected int total;

	public int getTotalProcessed() {
		return total;
	}

	private BoardFetcher fetcher;

	@Inject
	private DataService service;

	public Object call() throws Exception {
		run();
		return null;
	}

	public void run() {
		final FetcherThreadImpl parent = this;
		String board = fetcher.getBoard();
		parent.board = board;
		parent.current = 0;
		if (!parent.running) {
			return;
		}
		final int size = fetcher.getPageCount();
		if (size > 0) {
			int now = service.getLastId(board);
			List<Integer> list = new AbstractList<Integer>() {
				public Integer get(int i) {
					return i;
				}

				public int size() {
					return size;
				}
			};
			Comparator<Integer> comparator = new Comparator<Integer>() {
				public int compare(Integer a, Integer b) {
					if (!parent.running) {
						return 0;
					}
					PostItem[] items = fetcher.getPostItems(a + 1, false);
					if (b < items[0].getId()) {
						return 1;
					} else if (b > items[items.length - 1].getId()) {
						return -1;
					} else {
						return 0;
					}
				}
			};
			int num;
			if (comparator.compare(size - 1, now) == 0) {
				num = size - 1;
			} else {
				num = Collections.binarySearch(list, now, comparator);
			}
			if (!parent.running) {
				return;
			}
			if (num >= 0) {
				num++;
			} else if (num == -1) {
				num = 1;
			} else {
				return;
			}
			for (int i = num; i <= size; i++) {
				if (!parent.running) {
					return;
				}
				for (PostItem item : fetcher.getPostItems(i, false)) {
					if (!parent.running) {
						return;
					}
					int id = item.getId();
					if (id > now) {
						Post post = fetcher.getPost(item);
						if (!parent.running) {
							return;
						}
						if (post != null) {
							service.savePost(item, post);
							now = id;
							parent.current++;
							parent.total++;
						} else {
							log.warn("有一篇文章没有抓下来(" + board + ")(" + item.getId() + ")");
						}
					}
				}
			}
		}
	}
}